package com.syh.jn.scm.infrastructure.eventBus.reflex;

import cn.redscarf.commons.util.exception.IllegalParameterException;
import com.alibaba.dubbo.rpc.RpcException;
import com.syh.core.ddd.domain.DomainEvent;
import com.syh.core.ddd.event.DomainEventBus;
import com.syh.core.eventBus.EventHandle;
import com.syh.jn.scm.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ReflexEventBus implements DomainEventBus {

	private static ReflexEventBus reflexEventBus;
	private Map<String, List<EventHandle>> eventHandleMap = new HashMap<>();
	private Logger logger = LoggerFactory.getLogger(ReflexEventBus.class);

	private ReflexEventBus() {

	}

	public static ReflexEventBus getEventBus() {
		if (reflexEventBus == null) {
			reflexEventBus = new ReflexEventBus();
		}
		return reflexEventBus;
	}

	@Override
	public void subscribe(String eventName, EventHandle eventHandle) {
		if (this.eventHandleMap.get(eventName) == null) {
			List<EventHandle> eventHandleList = new ArrayList<>();
			this.eventHandleMap.put(eventName, eventHandleList);
		}
		this.eventHandleMap.get(eventName).add(eventHandle);
	}

	@Override
	public void publicEvent(DomainEvent domainEvent) {
		List<EventHandle> eventHandleList = eventHandleMap.get(domainEvent.getEventName());
		try{
			for(EventHandle eventHandle:eventHandleList){
				eventHandle.handle(domainEvent);
			}
		} catch (InvocationTargetException ite) {
			logger.error(ite.getMessage(), ite);
			if (ite.getTargetException() instanceof BusinessException) {
				throw new BusinessException(ite.getTargetException().getMessage());
			}
			if (ite.getTargetException() instanceof IllegalParameterException) {
				throw new IllegalParameterException(ite.getTargetException().getMessage());
			}
			throw new RpcException(ite.getTargetException().getMessage());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new RpcException(e.getMessage());
		}
	}


}
